"""
此模块用于唤醒登陆界面。
1.初始化登陆界面
2.添加功能以完成表单信息采集、验证以及邮箱验证的任务
3.完成验证登陆后跳转至主界面
"""
import re
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from client.Call_index import *
from client.client_smtp import *
from client.client_pop import *
from client.win_login import Ui_MainWindow as loginWindow


class Call_login(QMainWindow, loginWindow):

    def __init__(self, parent=None):

        """
        初始化窗口：设置窗口属性、绑定信号和槽
        :param parent: loginWindow(Qt designer 完成)，Qmainwindow
        """
        super(Call_login, self).__init__(parent)
        self.setupUi(self)
        self.setupUiWin()
        """
        定义参数
        """
        self.index_win = Call_index()
        self.clientPop = None
        self.clientSmtp = None
        self.is_smtp_falg = False
        self.is_pop_falg = False
        self.confirm_smtp = False
        self.confirm_pop = False

        """
        smtp登陆验证线程初始化及绑定信号槽
        1、线程结束发出信号给槽函数display_is_smtp_login同时关闭计时器
        2、计时器超时发出信号关闭计时器同时杀死线程
        """
        self.clock_confirm_smtp_login = QTimer()
        self.thread_confirm_smtp_login = Confirm_smtp_login()
        self.thread_confirm_smtp_login.trigger[ClientSmtp, bool, list].connect(self.display_is_smtp_login)
        self.thread_confirm_smtp_login.trigger.connect(self.clock_confirm_smtp_login.stop)
        self.clock_confirm_smtp_login.timeout.connect(self.clock_confirm_smtp_login.stop)
        self.clock_confirm_smtp_login.timeout.connect(self.thread_confirm_smtp_login.terminate)

        """
        pop登陆验证线程初始化及绑定信号槽
        1、线程结束发出信号给槽函数display_is_pop_login同时关闭计数器
        2、计时器超时发出信号关闭计时器同时杀死线程
        """
        self.clock_confirm_pop_login = QTimer()
        self.thread_confirm_pop_login = Confirm_pop_login()
        self.thread_confirm_pop_login.trigger[ClientPop, bool, list].connect(self.display_is_pop_login)
        self.thread_confirm_pop_login.trigger.connect(self.clock_confirm_pop_login.stop)
        self.clock_confirm_pop_login.timeout.connect(self.clock_confirm_pop_login.stop)
        self.clock_confirm_pop_login.timeout.connect(self.thread_confirm_pop_login.terminate)

        """
        pop连接验证线程初始化及绑定信号槽
        1、线程结束发出信号给槽函数display_is_smtp同时关闭计时器
        2、计时器超时发出信号关闭计时器，杀死线程并通知display_is_smtp函数连接失败
        """
        self.clock_confirm_smtp = QTimer()
        self.thread_confirm_smtp = Confirm_smtp()
        self.thread_confirm_smtp.trigger[ClientSmtp, bool, list].connect(self.display_is_smtp)
        self.thread_confirm_smtp.trigger.connect(self.clock_confirm_smtp.stop)
        self.clock_confirm_smtp.timeout.connect(self.clock_confirm_smtp.stop)
        self.clock_confirm_smtp.timeout.connect(self.thread_confirm_smtp.terminate)
        self.clock_confirm_smtp.timeout.connect(lambda: self.display_is_smtp(ClientSmtp, False, ['smtp连接超时，验证失败...']))

        """
        pop连接验证线程初始化及绑定信号槽
        1、线程结束发出信号给槽函数display_is_pop同时关闭计时器
        2、计时器超时发出信号关闭计时器，杀死线程并通知display_is_pop函数连接失败
        """
        self.clock_confirm_pop = QTimer()
        self.thread_confirm_pop = Confirm_pop()
        self.thread_confirm_pop.trigger[ClientPop, bool, list].connect(self.display_is_pop)
        self.thread_confirm_pop.trigger.connect(self.clock_confirm_pop.stop)
        self.clock_confirm_pop.timeout.connect(self.thread_confirm_pop.terminate)
        self.clock_confirm_pop.timeout.connect(self.clock_confirm_pop.stop)
        self.clock_confirm_pop.timeout.connect(lambda: self.display_is_pop(ClientPop, False, ['pop连接超时，验证失败...']))

        """
        绑定信号槽
        1、‘登陆’按钮绑定槽函数verify_smtp_login
        2、‘Add Host’按钮绑定槽函数openSmtpHost，openSmtpPort
        3、‘Add Port’按钮绑定槽函数openSmtpPort，openPopPort
        4、捕获到输入框结束编辑绑定槽函数
        5、isSmtpSSL,isPopSSL按钮更换状态时杀死线程thread_confirm_smtp，thread_confirm_pop并通知槽函数verify_pop，verify_pop
        """
        self.login_button.clicked.connect(self.verify_smtp_login)
        self.addPopHost.clicked.connect(self.openPopHost)
        self.addPopport.clicked.connect(self.openPopPort)
        self.addSmtpHost.clicked.connect(self.openSmtpHost)
        self.addSmtpPort.clicked.connect(self.openSmtpPort)
        self.account.editingFinished.connect(self.confirm_email_form)
        self.linedit_smtp_port.editingFinished.connect(self.verify_smtp)
        self.linedit_smtp_host.editingFinished.connect(self.verify_smtp)
        self.isSmtpSSL.toggled.connect(self.thread_confirm_smtp.terminate)
        self.isSmtpSSL.toggled.connect(self.verify_smtp)
        self.linedit_pop_host.editingFinished.connect(self.verify_pop)
        self.linedit_pop_port.editingFinished.connect(self.verify_pop)
        self.isPopSSL.toggled.connect(self.thread_confirm_pop.terminate)
        self.isPopSSL.toggled.connect(self.verify_pop)
        self.labelX.trigger.connect(self.close)
        self.labelOne.trigger.connect(self.showMinimized)

    """
    性质：槽函数
    作用：用于快捷设置Pop主机地址
    """
    def openPopHost(self):
        items = ["pop.163.com", "pop.qq.com"]
        item, ok = QInputDialog.getItem(self, "select smtp host", "Smtp Host", items, 0, False)
        if ok and item:
            self.linedit_pop_host.setText(item)
            self.verify_pop()

    """
    性质：槽函数
    作用：用于快捷设置Pop端口号
    """
    def openPopPort(self):
        items = ["110", "995"]
        item, ok = QInputDialog.getItem(self, "select pop port", "Pop Port", items, 0, False)
        if ok and item:
            self.linedit_pop_port.setText(item)
            self.verify_pop()

    """
    性质：槽函数
    作用：用于快捷设置Smtp主机地址
    """
    def openSmtpHost(self):
        items = ["smtp.163.com", "smtp.qq.com"]
        item, ok = QInputDialog.getItem(self, "select smtp host", "Smtp Host", items, 0, False)
        if ok and item:
            self.linedit_smtp_host.setText(item)
            self.verify_smtp()

    """
    性质：槽函数
    作用：用于快捷设置Smtp端口号
    """
    def openSmtpPort(self):
        items = ["25", "465", "587"]
        item, ok = QInputDialog.getItem(self, "select smtp port", "Smtp Port", items, 0, False)
        if ok and item:
            self.linedit_smtp_port.setText(item)
            self.verify_smtp()

    """
    用于初始化窗口
    """
    def setupUiWin(self):
        desktopWin = QDesktopWidget().screenGeometry()
        selfWin = self.geometry()
        self.password.setEchoMode(QLineEdit.Password)
        self.login_button.setEnabled(False)
        self.linedit_smtp_host.setPlaceholderText("请输入SMTP服务器地址...")
        self.linedit_smtp_port.setPlaceholderText("请输入SMTP服务器端口号...")
        self.linedit_pop_host.setPlaceholderText("请输入POP服务器端口号...")
        self.linedit_pop_port.setPlaceholderText("请输入POP服务器地址...")
        self.move((desktopWin.width() - selfWin.width()) / 2, (desktopWin.height() - selfWin.height()) / 2)

        self.labelOne = MyLabel(self.centralwidget)
        self.labelOne.setGeometry(QRect(370, 20, 31, 31))
        self.labelOne.setObjectName("labelOne")
        self.labelOne.raise_()
        # self.labelOne.setText(QCoreApplication.translate("MainWindow", "2"))

        self.labelX = MyLabel(self.centralwidget)
        self.labelX.setGeometry(QRect(410, 20, 31, 31))
        self.labelX.setObjectName("labelX")
        # self.labelX.setText(QCoreApplication.translate("MainWindow", "3"))

        self.labelIcon.setPixmap(QPixmap("client/image/email(1).png"))
        self.labelIcon.setScaledContents(True)
        self.labelX.setPixmap(QPixmap("client/image/x.png"))
        self.labelX.setScaledContents(True)
        self.labelOne.setPixmap(QPixmap("client/image/small.png"))
        self.labelOne.setScaledContents(True)
        self.pushbuttonAccount.setIcon(QIcon("client/image/user.png"))
        self.pushbuttonPassword.setIcon(QIcon("client/image/password.png"))
        # 设置无标题栏
        self.setWindowFlags(Qt.FramelessWindowHint)
        # 设置窗口透明
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.loadQss()
    def loadQss(self):
        qssPath = 'client/qss/login.qss'
        with open(qssPath, 'r') as f:
                qssStyle = f.read()
        self.setStyleSheet(qssStyle)
    """
    性质：槽函数
    作用：用于smtp连接验证
    """
    def verify_smtp(self):
        self.confirm_smtp = False
        smtp_host = self.linedit_smtp_host.text()
        smtp_port = self.linedit_smtp_port.text()
        self.labelSmtp.setText("")
        if (not (smtp_host == "" or smtp_port == "")):
            is_smtp_ssl = self.isSmtpSSL.isChecked()
            self.thread_confirm_smtp.setAttribute(smtp_host, smtp_port, is_smtp_ssl)
            self.clock_confirm_smtp.start(2000)
            self.thread_confirm_smtp.start()
        else:
            self.labelSmtp == ""

    """
    性质：槽函数
    作用：用于pop连接验证
    """
    def verify_pop(self):
        self.confirm_pop = False
        pop_host = self.linedit_pop_host.text()
        pop_port = self.linedit_pop_port.text()
        self.labelPop.setText("")
        if (not (pop_host == "" or pop_port == "")):
            is_pop_ssl = self.isPopSSL.isChecked()
            self.thread_confirm_pop.setAttribute(pop_host, pop_port, is_pop_ssl)
            self.clock_confirm_pop.start(2000)
            self.thread_confirm_pop.start()
        else:
            self.labelPop == ""

    """
    性质：槽函数
    作用：用于smtp登陆验证
    """
    def verify_smtp_login(self):
        account = self.account.text()
        password = self.password.text()
        if account == "":
            print(QMessageBox.critical(self, "Error", "用户名不能为空！！！", QMessageBox.Yes))
        elif password == "":
            print(QMessageBox.critical(self, "Error", "密码不能为空！！！", QMessageBox.Yes))
        else:
            self.is_pop_falg = False
            self.is_smtp_falg = False
            self.thread_confirm_smtp_login.setAttribute(self.clientSmtp, account, password)
            self.clock_confirm_smtp_login.start(2000)
            self.thread_confirm_smtp_login.run()

    """
    性质：槽函数
    作用：用于pop登陆验证
    """
    def verify_pop_login(self):
        account = self.account.text()
        password = self.password.text()
        self.is_pop_falg = False
        self.is_smtp_falg = False
        self.thread_confirm_pop_login.setAttribute(self.clientPop, account, password)
        self.clock_confirm_pop_login.start(2000)
        self.thread_confirm_pop_login.run()


    """
    性质：槽函数
    作用：用于判断smtp连接是否成功
    """
    def display_is_smtp(self, ClientSmtp, bool, list):
        if bool == True:
            self.labelSmtp.setText("验证成功")
            self.clientSmtp = ClientSmtp
            self.confirm_smtp = True
            print("smtp验证成功...")
            if self.confirm_pop == True:
                self.login_button.setEnabled(True)
        else:
            self.login_button.setEnabled(False)
            for index in range(len(list)):
                self.labelSmtp.setText("验证失败")
                print("%s %s" % ("错误信息: ", list[index]))
    """
    性质：槽函数
    作用：用于判断pop连接是否成功
    """
    def display_is_pop(self, ClientPop, bool, list):
        if bool == True:
            self.labelPop.setText("验证成功")
            self.clientPop = ClientPop
            self.confirm_pop = True
            print("pop验证成功...")
            if (self.confirm_smtp == True):
                self.login_button.setEnabled(True)
        else:
            self.login_button.setEnabled(False)
            for index in range(len(list)):
                self.labelPop.setText("验证失败")
                print("%s %s" % ("错误信息: ", list[index]))
    """
    性质：槽函数
    作用：用于判断smtp登陆是否成功
    """
    def display_is_smtp_login(self, clientSmtp, bool, list):
        if bool == True:
            print("smtp登陆成功...")
            self.is_smtp_falg = True
            self.clientSmtp = clientSmtp
            self.verify_pop_login()
        else:
            print("%s\t%s" % ("smtp登陆失败...", list))
            QMessageBox.information(self,"登陆失败","SMTP验证登陆失败，请检查用户名和密码...",QMessageBox.Yes)
    """
    性质：槽函数
    作用：用于判断pop登陆是否成功
    """
    def display_is_pop_login(self, clientPop, bool, list):
        if bool == True:
            print("pop登陆成功...")
            self.is_pop_falg = True
            self.clientPop = clientPop
            self.jumpWIn(self.clientSmtp, self.clientPop)
        else:
            print("%s\t%s" % ("pop登陆失败...", list))
            QMessageBox.information(self, "登陆失败", "POP验证登陆失败，你可以尝试更换端口号...", QMessageBox.Yes)
    """
    性质：槽函数
    作用：用于判断用户账号格式是否正确
    """
    def confirm_email_form(self):
        account = self.account.text()
        if account == "":
            self.account.setPlaceholderText("")
        elif (re.match(r'^[0-9a-zA-Z_]{0,19}@[0-9a-zA-Z]{1,13}\.[com,cn,net]{1,3}$', account) == None):
            self.account.clear()
            self.account.setPlaceholderText("邮箱格式错误")
            self.account.setFocus()
    """
    作用：用于验证成功之后跳转窗口
    """
    def jumpWIn(self, clientSmtp, clientPop):
        self.close()
        self.index_win.show()
        self.index_win.set_smtp(clientSmtp)
        self.index_win.set_pop(clientPop)
        self.index_win.getEmail()
        print("%s,%s" % ("欢迎回来 ",clientSmtp.get_username()))


    '''
    event.globalPos()获取到的是鼠标相对于屏幕左上角的位置
    self.pos()获取到的是窗口左上角相对于屏幕左上角的位置
    '''
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_flag = True
            self.m_Position = event.globalPos() - self.pos()  # 获取鼠标相对窗口的位置
            event.accept()

    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_flag:
            print(self.m_Position)
            self.move(QMouseEvent.globalPos() - self.m_Position)  # 更改窗口位置
            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):
        self.m_flag = False

"""
性质：带点击功能的label
"""
class MyLabel(QLabel):
    trigger = pyqtSignal()
    def __init__(self,parent=None):
        super(MyLabel, self).__init__(parent)
    def mouseReleaseEvent(self, QMouseEvent):
        if QMouseEvent.button() == Qt.LeftButton:
            self.trigger.emit()
"""
性质：线程类
作用：用于smtp登陆
"""
class Confirm_smtp_login(QThread):
    trigger = pyqtSignal(ClientSmtp, bool, list)
    smtp_login_flag = False

    client_smtp = ClientSmtp()
    account = None
    password = None

    def __init__(self):
        super(Confirm_smtp_login, self).__init__()

    def setAttribute(self, client_smtp, account, password):
        self.client_smtp = client_smtp
        self.account = account
        self.password = password

    def run(self):
        errlist = []
        try:
            self.smtp_login_flag, msg = self.client_smtp.login(self.account, self.password)
            print(self.account)
            if self.smtp_login_flag == False:
                errlist.append(msg)
        except Exception as err:
            errlist.append(err)
        self.trigger.emit(self.client_smtp, self.smtp_login_flag, errlist)

"""
性质：线程类
作用：用于pop登陆
"""
class Confirm_pop_login(QThread):
    trigger = pyqtSignal(ClientPop, bool, list)
    pop_login_flag = False
    client_pop = ClientPop()
    account = None
    password = None

    def __init__(self):
        super(Confirm_pop_login, self).__init__()

    def setAttribute(self, client_pop, account, password):
        self.client_pop = client_pop
        self.account = account
        self.password = password

    def run(self):
        errlist = []
        try:
            self.pop_login_flag, msg = self.client_pop.login(self.account, self.password)
            if self.pop_login_flag == False:
                errlist.append(msg)
        except Exception as err:
            errlist.append(err)
        self.trigger.emit(self.client_pop, self.pop_login_flag, errlist)


"""
性质：线程类
作用：用于smtp连接
"""

class Confirm_smtp(QThread):
    trigger = pyqtSignal(ClientSmtp, bool, list)
    is_smtp_ok = False
    smtp_host = None
    smtp_port = None
    is_smtp_ssl = None

    def __init__(self):
        super(Confirm_smtp, self).__init__()

    def setAttribute(self, smtp_host, smtp_port, is_smtp_ssl):
        self.smtp_host = smtp_host
        self.smtp_port = smtp_port
        self.is_smtp_ssl = is_smtp_ssl

    def run(self):
        errList = []
        try:
            self.is_smtp_ok = False
            self.client_smtp = ClientSmtp(self.smtp_host, self.smtp_port)
            self.client_smtp.get_smtp(self.is_smtp_ssl)
            self.is_smtp_ok, msg = self.client_smtp.get_connect()
            if self.is_smtp_ok == False:
                errList.append(msg)
        except Exception as err:
            errList.append(err)
        self.trigger.emit(self.client_smtp, self.is_smtp_ok, errList)


"""
性质：线程类
作用：用于pop连接
"""

class Confirm_pop(QThread):
    trigger = pyqtSignal(ClientPop, bool, list)
    is_pop_ok = False
    pop_host = None
    pop_port = None
    is_pop_ssl = None

    def __init__(self):
        super(Confirm_pop, self).__init__()

    def setAttribute(self, pop_host, pop_port, is_pop_ssl):
        self.pop_host = pop_host
        self.pop_port = pop_port
        self.is_pop_ssl = is_pop_ssl

    def run(self):
        errList = []
        try:
            self.is_pop_ok = False
            self.client_pop = ClientPop(self.pop_host, self.pop_port)
            self.client_pop.get_pop(self.is_pop_ssl)
            self.is_pop_ok, msg = self.client_pop.hello()
            if self.is_pop_ok == False:
                errList.append(msg)
        except Exception as err:
            errList.append(err)
        self.trigger.emit(self.client_pop, self.is_pop_ok, errList)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = Call_login()
    myWin.show()
    sys.exit(app.exec_())